package _str

import org.junit.Assert
import org.junit.Test

/**
 * https://leetcode.cn/problems/ambiguous-coordinates/description
 * 816. 模糊坐标
 *
 * 题型：字符串-枚举
 * ```
 * 我们有一些二维坐标，如 "(1, 3)" 或 "(2, 0.5)"，然后我们移除所有逗号，小数点和空格，得到一个字符串S。返回所有可能的原始字符串到一个列表中。
 * 原始的坐标表示法不会存在多余的零，所以不会出现类似于"00", "0.0", "0.00", "1.0", "001", "00.01"或一些其他更小的数来表示坐标。此外，一个小数点前至少存在一个数，所以也不会出现“.1”形式的数字。
 * 最后返回的列表可以是任意顺序的。而且注意返回的两个数字中间（逗号之后）都有一个空格。
 *

 * 示例 1:
 * 输入: "(123)"
 * 输出: ["(1, 23)", "(12, 3)", "(1.2, 3)", "(1, 2.3)"]
 *
 * 示例 2:
 * 输入: "(00011)"
 * 输出:  ["(0.001, 1)", "(0, 0.011)"]
 * 解释:
 * 0.0, 00, 0001 或 00.01 是不被允许的。
 *
 * 示例 3:
 * 输入: "(0123)"
 * 输出: ["(0, 123)", "(0, 12.3)", "(0, 1.23)", "(0.1, 23)", "(0.1, 2.3)", "(0.12, 3)"]

 * 示例 4:
 * 输入: "(100)"
 * 输出: ["(10, 0)"]
 * 解释:
 * 1.0 是不被允许的。
 *
 *
 * 提示:
 * 4 <= S.length <= 12.
 * S[0] = "(", S[S.length - 1] = ")", 且字符串 S 中的其他元素都是数字。
 *
 * 思路：![leetcode_816.jpg](../../../../images/leetcode_816.jpg)
 * ```
 */
class leekcode_816 {
    @Test
    fun test_1() {
        val result = ambiguousCoordinates("(123)")
        val expected = arrayListOf("(1, 2.3)", "(1, 23)", "(1.2, 3)", "(12, 3)")
        Assert.assertEquals(expected, result)
    }

    @Test
    fun test_2() {
        val result = ambiguousCoordinates("(00011)")
        val expected = arrayListOf("(0, 0.011)", "(0.001, 1)")
        Assert.assertEquals(expected, result)
    }

    @Test
    fun test_3() {
        val result = ambiguousCoordinates("(0123)")
        val expected = arrayListOf("(0, 1.23)", "(0, 12.3)", "(0, 123)", "(0.1, 2.3)", "(0.1, 23)", "(0.12, 3)")
        Assert.assertEquals(expected, result)
    }

    @Test
    fun test_4() {
        val result = ambiguousCoordinates("(100)")
        val expected = arrayListOf("(10, 0)")
        Assert.assertEquals(expected, result)
    }

    fun ambiguousCoordinates(s: String): List<String> {
        /**
        思路：枚举
        1 去掉(),
        2 For -  拆成2个字符串 s1 和 s2
        3 使用 给s1和s2 加. ，得出所有可能
        4 For For - 组合 加.后的s1 和 s2
         */
        val result: ArrayList<String> = ArrayList()
        // 1 去掉() (123) -> 123
        val s = s.substring(1 until s.length - 1)
        for (i in 1 until s.length) {
            // 拆分成两个字符串
            val s1: String = s.substring(0 until i) // [0. i)
            val s2: String = s.substring(i until s.length) // [i, size)
            // println("s1=$s1,s2=$s2")

            // 给每个字符串.， 得出所有可能
            // if(s1=="01" && s2 == "23"){
            val list1: ArrayList<String> = convert(s1)
            val list2: ArrayList<String> = convert(s2)
            println("s1=[$s1] to ${list1.toString()}")
            println("s2=[$s2] to ${list2.toString()}")

            // 组合带.字符串的所有可能
            for (item1 in list1) {
                for (item2 in list2) {
                    val node = "($item1, $item2)"
                    result.add(node)
                }
            }
            // }
        }
        return result
    }

    fun convert(s: String): ArrayList<String> {
        val r: ArrayList<String> = ArrayList()
        if (s.length == 1) {
            r.add(s)
            // println("target=$s")
            return r
        }
        // 过滤不合法元素
        for (i in 1 until s.length + 1) {
            // 拆分整数部分
            val s1: String = s.substring(0 until i) // [0, i)
            // 拆分小数部分
            val s2: String = s.substring(i until s.length) // [i, size)
            // println("convert,s1=$s1,s2=$s2")

            //整数部分长度>1时，不能以0开头
            if (s1.length > 1 && s1.startsWith("0")) {
                continue
            }
            //小数部分长度>0时，不能以0结尾
            if (s2.length > 0 && s2.endsWith("0")) {
                continue
            }
            if (s2.length > 0) {
                val target = "$s1.$s2"
                // println("s=$s,s1=$s1, s2=$s2, target=$target")
                r.add(target)
            } else {
                // println("s=$s,s1=$s1, s2=$s2, target=$s1")
                r.add(s1)
            }
        }
        return r
    }

}